package org.piwicode.bywordofmouth.net;

import com.google.common.base.Preconditions;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author pierre
 */
class ServerSocketRunnable implements Runnable, Cancellable {

    private final static Logger logger = Logger.getLogger(ServerSocketRunnable.class.getName());
    private final Socket socket;
    private final Service service;

    public ServerSocketRunnable(Socket socket, Service service) {
        this.socket = Preconditions.checkNotNull(socket);
        this.service = Preconditions.checkNotNull(service);
    }

    @Override
    public void run() {
        try {
            doRun();
        } catch (IOException ex) {
            logger.log(Level.INFO, "Server socket closed");
        } catch (ReflectiveOperationException ex) {
            Logger.getLogger(ServerSocketRunnable.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public void cancel() {
        try {
            socket.close();
        } catch (IOException ex) {
            logger.log(Level.SEVERE, "Failed to interrupt the server thread", ex);
        }
    }

    private void doRun() throws IOException, ReflectiveOperationException {
        final ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
        final ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
        while (true) {
            final ServiceRequest req = (ServiceRequest) ois.readObject();
            oos.writeObject(req.call(service));
            oos.reset();
            oos.flush();
        }
    }
}
